/*
 * memory.c
 *
 *  Created on: 2011/07/10
 *      Author: AKS
 */

#include "core/include/aks_processor.h"
#include "core/include/process.h"
#include "core/include/types.h"

#include "include/memory.h"
#include "chip/include/chip_dma.h"

#define MEM_MAP_MSK  0x01FF
#define MEM_MAP_SIZE 512

#define EMPTY        0

static WORD  blockSize;
static WORD  memoryMap[MEM_MAP_SIZE];
static DWORD memory_baseAdr;

/* system function for memory */
void InitMemory(DWORD baseAdr, DWORD size)
{
    blockSize = size / MEM_MAP_SIZE;
    memory_baseAdr = baseAdr;

    /* clear memory map */
    for(WORD i=0 ; i<MEM_MAP_SIZE ; ++i)
    {
        memoryMap[i] = EMPTY;
    }

    return;
}


BOOL Memory_check(DWORD baseAdr, DWORD size)
{
    return TRUE;
}

/* base function for memory allocate */
DWORD Memory_allocate(DWORD size)
{
	/* 1 search free area */
    /* 1.1  search enable area */
    WORD blocks   = (size + blockSize-1) / blockSize;
    WORD blockCnt = 0;
    WORD i;
	WORD blockHead;
	
	if(blocks == 0){
		return (DWORD)NULL;
	}	

    for(i=0 ; i<MEM_MAP_SIZE ; ++i){
    	blockCnt = (memoryMap[i] == EMPTY) ? blockCnt+1 : 0;
        if(blockCnt == blocks){
            break;
        }
    }

	blockHead = (i+1)-blocks;


    /* 1.2 there is no free area */
    if(i == MEM_MAP_SIZE){
        return (DWORD)NULL;
    }

    /* 2. allocate memory */
    /* 2.1 create magic number */
	/* head  */
	WORD magicNum = (DWORD)(memory_baseAdr + (blockHead*blockSize)) >> 8;

    /* 2.2 set magic Number */
    for(WORD j=0 ; j<blocks ; ++j){
        memoryMap[blockHead+j] = magicNum;
    }

	/* 3 make pointer */
    return (DWORD)(memory_baseAdr + (blockHead*blockSize));

}
BOOL   Memory_free(DWORD adr)
{
    /* search allocated block */

	/* free blocks */
	
	return FALSE;
}

/* DMA function */
BOOL Memory_startDMA(DWORD src, DWORD dst, WORD size, DMA_FINISHED_CALLBACK callback)
{
    if( FALSE == DMA_is_Free() )
    {
        return FALSE;
    }

	DMA_Enabe();

	DMA_setup(src, dst, size, callback);

	DMA_startTransmit();

	return TRUE;

}



